/*
 * =====================================================================================
 *
 *       Filename:  contact_mysql.cc
 *
 *    Description:  decalarition for MySQL adapter of contact.
 *
 *        Version:  1.0
 *        Created:  2013年05月20日 12时24分23秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Wu Yuxin
 *        Company:  www.Qihoo.net
 *
 * =====================================================================================
 */

#include "contact_mysql.h"

#include <boost/format.hpp>

#include "base/logging.h"
#include "base/config_reader.h"
#include "database/scoped_connection.h"

namespace imserver {

ContactMySql::ContactMySql(const std::string& database,
                           const std::string& addr,
                           const std::string& user,
                           const std::string& pwd) : conn_pool_(database.c_str(), addr.c_str(), user.c_str(), pwd.c_str()) {
  LOG_INFO("ContactMySql constructor.");
}

int ContactMySql::Insert(const int64_t sender, const int64_t receiver, const time_t timestamp) {
  LOG_INFO("[ContactMySql::Insert] begin.");

  mysqlpp::ScopedConnection scoped_conn(conn_pool_);
  if (!scoped_conn) {
    LOG_ERROR("Failed to get a connection from database-pool.");
    return -2;
  }

  mysqlpp::Query query(scoped_conn->query());
  query << boost::str(boost::format("INSERT INTO recent_contacts(uid, cid, last_time) VALUES (%1%, %2%, FROM_UNIXTIME(%3%)) "
        "ON DUPLICATE KEY UPDATE last_time=FROM_UNIXTIME(%3%)") % sender % receiver % timestamp);

  try {
    bool ret = query.exec();
    LOG_INFO("Insert contacts with result  " << ret);
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -1;
  }

  return 0;
}

int ContactMySql::Delete(const int64_t sender, const int64_t receiver) {
  LOG_INFO("[ContactMySql::Delete] begin.");

  mysqlpp::ScopedConnection scoped_conn(conn_pool_);
  if (!scoped_conn) {
    LOG_ERROR("[DeleteChated] failed to get a connection from database-pool.");
    return -2;
  }

  mysqlpp::Query query(scoped_conn->query());
  query << boost::str(boost::format("DELETE FROM recent_contacts WHERE uid=%1% AND cid=%2%") % sender % receiver);

  try {
    bool ret = query.exec();
    LOG_INFO("Delete from contacs with result " << ret);
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -1;
  }

  return 0;
}

int ContactMySql::Select(RecentContactList& contacts, const int64_t uid, const int32_t offset, const int32_t count) {
  LOG_INFO("[ContactMySql::Select] begin.");

  mysqlpp::ScopedConnection scoped_conn(conn_pool_);
  if (!scoped_conn) {
    LOG_ERROR("[GetChatedList] failed to get a connection from database-pool.");
    return -2;
  }

  mysqlpp::Query query(scoped_conn->query());
  query << boost::str(boost::format("SELECT cid, UNIX_TIMESTAMP(last_time) AS last_time "
        "FROM recent_contacts WHERE uid=%1% ORDER BY last_time DESC LIMIT %2%, %3%") % uid % offset % count);

  try {
    mysqlpp::UseQueryResult ret = query.use();
    LOG_INFO("select recent_chated with result " << ret);
    if (ret) {
      while(mysqlpp::Row row = ret.fetch_row()) {
        contacts.push_back(RecentContact());
        RecentContact &c = contacts.back();
        c.__set_uid(row["cid"]);
        c.__set_timestamp(row["last_time"]);
      }
    }
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -1;
  }

  return 0;
}


int ContactMySql::UpdateFavorite(const int64_t sender, const int64_t receiver, const time_t timestamp) {
  mysqlpp::ScopedConnection scoped_conn(conn_pool_);
  if (!scoped_conn) {
    LOG_ERROR("Failed to get a connection from database-pool.");
    return -2;
  }

  mysqlpp::Query query(scoped_conn->query());
  query << boost::str(boost::format("INSERT INTO favorite_contacts(uid, cid, last_time) VALUES (%1%, %2%, FROM_UNIXTIME(%3%)) "
        "ON DUPLICATE KEY UPDATE last_time=FROM_UNIXTIME(%3%)") % sender % receiver % timestamp);

  try {
    bool ret = query.exec();
    LOG_INFO("Insert friends with result  " << ret);
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -1;
  }
  return 0;
}

int ContactMySql::UpdateRemark(const int64_t sender, const int64_t receiver, const std::string& remark, const time_t timestamp) {
  mysqlpp::ScopedConnection scoped_conn(conn_pool_);
  if (!scoped_conn) {
    LOG_ERROR("Failed to get a connection from database-pool.");
    return -2;
  }

  mysqlpp::Query query(scoped_conn->query());
  query << "INSERT INTO contacts_remark(uid, cid, remark, last_time) VALUES (" << sender << ',' << receiver << ','
    << mysqlpp::quote << remark << ", FROM_UNIXTIME(" << timestamp << ")) ON DUPLICATE KEY UPDATE remark=" << mysqlpp::quote << remark
    << ", last_time=FROM_UNIXTIME(" << timestamp << ")";

  try {
    bool ret = query.exec();
    LOG_INFO("update remark with result  " << ret);
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR(query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -1;
  }

  return 0;
}

}
